<?php
require_once __DIR__ . '/ssh.class.php';

class Sftp extends Ssh {
	private $_aConn = array ();
	private $_rConn;
	
	public function connect($sHost, $sUser, $sPassword) {
		try {
			list ( $sHost, $iPort ) = explode ( ':', $sHost );
			$iPort = intval ( $iPort ) ? $iPort : 22;
			$sId = $this->_getId ( $sHost, $iPort );
			if (isset ( $this->_aConn [$sId] )) {
				return $this->_aConn [$sId];
			}
			$rSshConn = parent::connect ( $sHost . ':' . $iPort, $sUser, $sPassword );
			$rConn = ssh2_sftp ( $rSshConn );
			$this->_aConn [$sId] = $rConn;
			$this->_rConn = $rConn;
			return $rConn;
		} catch ( ExceptionExt $e ) {
			$e->showError ();
		}
	}
	
	private function _getId($sHost, $iPort) {
		return md5 ( $sHost . ':' . $iPort );
	}
	
	public function get($sRemotePath, $sLocalPath, $rConn = null) {
		if ($rConn == null) {
			$rConn = $this->_rConn;
		}
		if (substr ( $sRemotePath, 0, 1 ) != '/') {
			$sSshPath = '/' . $sRemotePath;
		} else {
			$sSshPath = $sRemotePath;
		}
		$sSshPath = 'ssh2.sftp://' . $rConn . $sSshPath;
		return @copy ( $sSshPath, $sLocalPath );
	}
	
	public function put($sLocalPath, $sRemotePath, $rConn = null) {
		if ($rConn == null) {
			$rConn = $this->_rConn;
		}
		if (substr ( $sRemotePath, 0, 1 ) != '/') {
			$sSshPath = '/' . $sRemotePath;
		} else {
			$sSshPath = $sRemotePath;
		}
		$sSshPath = 'ssh2.sftp://' . $rConn . $sSshPath;
		return @copy ( $sLocalPath, $sSshPath );
	}
	
	public function ls($sPath = '/', $sType = 'all', $sMatch = null, $rConn = null) {
		if ($rConn == null) {
			$rConn = $this->_rConn;
		}
		if (substr ( $sPath, 0, 1 ) != '/') {
			$sSshPath = '/' . $sPath;
		} else {
			$sSshPath = $sPath;
		}
		$sSshPath = 'ssh2.sftp://' . $rConn . $sSshPath;
		try {
			$aFiles = @scandir ( $sSshPath );
			if ($aFiles == false) {
				throw new ExceptionExt ( '目录' . $sPath . '不存在' );
			}
		} catch ( ExceptionExt $e ) {
			$e->showError ();
		}
		if ($sMatch != null && $sMatch != '*') {
			$sThisMatch = str_replace ( '.', '\.', $sMatch );
			$sThisMatch = str_replace ( '*', '.*', $sThisMatch );
			$sThisMatch = str_replace ( '?', '.?', $sThisMatch );
			$sThisMatch = '/^' . $sThisMatch . '$/';
		}
		foreach ( $aFiles as $sRow ) {
			if (! preg_match ( '/^[\.]+$/', $sRow )) {
				if ($sThisMatch != null && $sType != 'tree') {
					if (! preg_match ( $sThisMatch, $sRow )) {
						continue;
					}
				}
				$sFile = ssh2_sftp_realpath ( $rConn, $sPath . '/./' . $sRow );
				if ($sType == 'dir' && is_dir ( $sFile )) {
					$aResult [] = $sFile;
				} elseif ($sType == 'file' && ! is_dir ( $sFile )) {
					$aResult [] = $sFile;
				} elseif ($sType == 'all') {
					$aResult [] = $sFile;
				} elseif ($sType == 'tree') {
					if ($sThisMatch != null) {
						if (preg_match ( $sThisMatch, $sRow )) {
							$aResult [] = $sFile;
						}
					} else {
						$aResult [] = $sFile;
					}
					if (is_dir ( $sFile )) {
						$aResult = $this->_ls ( $sFile, 'tree', $sMatch, $aResult );
					}
				}
			}
		}
		return $aResult;
	}
	
	public function md($sPath, $rConn = null) {
		if ($rConn == null) {
			$rConn = $this->_rConn;
		}
		if (substr ( $sPath, 0, 1 ) != '/') {
			$sSshPath = '/' . $sPath;
		} else {
			$sSshPath = $sPath;
		}
		$sSshPath = 'ssh2.sftp://' . $rConn . $sSshPath;
		if (! is_dir ( dirname ( $sSshPath ) )) {
			$this->md ( dirname ( $sPath ), $rConn );
		}
		return @mkdir ( $sSshPath );
	}
	
	public function rm($sPath, $rConn = null) {
		if ($rConn == null) {
			$rConn = $this->_rConn;
		}
		if (substr ( $sPath, 0, 1 ) != '/') {
			$sSshPath = '/' . $sPath;
		} else {
			$sSshPath = $sPath;
		}
		$sSshPath = 'ssh2.sftp://' . $rConn . $sSshPath;
		if (is_dir ( $sSshPath )) {
			$aFile = scandir ( $sSshPath );
			$iCount = count ( $aFile );
			for($i = 2; $i < $iCount; $i ++) {
				$this->rm ( $sPath . '/' . $aFile [$i] );
			}
			return @rmdir ( $sSshPath );
		} else {
			return unlink ( $sSshPath );
		}
	}
}